import { pages, subPackages, tabBar } from '@/pages.json'
import { http } from '@/utils/http'

/** 判断当前页面是否是tabbar页  */
export const getIsTabbar = () => {
  if (!tabBar) {
    return false
  }
  if (!tabBar.list.length) {
    // 通常有tabBar的话，list不能有空，且至少有2个元素，这里其实不用处理
    return false
  }
  // getCurrentPages() 至少有1个元素，所以不再额外判断
  const lastPage = getCurrentPages().at(-1)
  const currPath = lastPage.route
  return !!tabBar.list.find((e) => e.pagePath === currPath)
}

/**
 * 获取当前页面路由的 path 路劲和 redirectPath 路径
 * path 如 ‘/pages/login/index’
 * redirectPath 如 ‘/pages/demo/base/route-interceptor’
 */
export const currRoute = () => {
  // getCurrentPages() 至少有1个元素，所以不再额外判断
  const lastPage = getCurrentPages().slice(-1)[0]
  const currRoute = (lastPage as any).$page
  // 经过多端测试，只有 fullPath 靠谱，其他都不靠谱
  const { fullPath } = currRoute as { fullPath: string }
  return getUrlObj(fullPath)
}

const ensureDecodeURIComponent = (url: string) => {
  if (url.startsWith('%')) {
    return ensureDecodeURIComponent(decodeURIComponent(url))
  }
  return url
}
/**
 * 解析 url 得到 path 和 query
 * 比如输入url: /pages/login/index?redirect=%2Fpages%2Fdemo%2Fbase%2Froute-interceptor
 * 输出: {path: /pages/login/index, query: {redirect: /pages/demo/base/route-interceptor}}
 */
export const getUrlObj = (url: string) => {
  const [path, queryStr] = url.split('?')

  const query: Record<string, string> = {}
  if (queryStr) {
    queryStr.split('&').forEach((item) => {
      const [key, value] = item.split('=')
      query[key] = ensureDecodeURIComponent(value) // 这里需要统一 decodeURIComponent 一下，可以兼容h5和微信y
    })
  }
  return { path, query }
}
/**
 * 得到所有的需要登录的pages，包括主包和分包的
 * 这里设计得通用一点，可以传递key作为判断依据，默认是 needLogin, 与 route-block 配对使用
 * 如果没有传 key，则表示所有的pages，如果传递了 key, 则表示通过 key 过滤
 */
export const getAllPages = (key = 'needLogin') => {
  // 这里处理主包
  const mainPages = [
    ...pages
      .filter((page) => !key || page[key])
      .map((page) => ({
        ...page,
        path: `/${page.path}`,
      })),
  ]
  // 这里处理分包
  const subPages: any[] = []
  subPackages.forEach((subPageObj) => {
    // console.log(subPageObj)
    const { root } = subPageObj

    subPageObj.pages
      .filter((page) => !key || page[key])
      .forEach((page: { path: string } & Record<string, any>) => {
        subPages.push({
          ...page,
          path: `/${root}/${page.path}`,
        })
      })
  })
  const result = [...mainPages, ...subPages]
  return result
}

/**
 * 得到所有的需要登录的pages，包括主包和分包的
 * 只得到 path 数组
 */
export const getNeedLoginPages = (): string[] => getAllPages('needLogin').map((page) => page.path)

/**
 * 得到所有的需要登录的pages，包括主包和分包的
 * 只得到 path 数组
 */
export const needLoginPages: string[] = getAllPages('needLogin').map((page) => page.path)

/**
 * @description 成功消息提示框
 * @param {String} title 提示的文字
 * @param {Number} duration 提示的延迟时间
 */
export const msgSuccess = (title, duration = 1500) => {
  if (title.length > 7) {
    return msgNone(title, duration)
  }
  uni.showToast({
    title,
    icon: 'success',
    duration,
  })
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(true)
    }, duration)
  })
}

/**
 * @description 失败消息提示框
 * @param {String} title 提示的文字，不能超过7个字符
 * @param {Number} duration 提示的延迟时间
 * @return {Promise}
 */
export const msgError = (title, duration = 1500) => {
  if (title.length > 7) {
    return msgNone(title, duration)
  }
  uni.showToast({
    title,
    icon: 'error',
    duration,
  })
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(true)
    }, duration)
  })
}

/**
 * @description 消息提示框
 * @param {String} title 提示的文字
 * @param {Number} duration 提示的延迟时间
 * @returns {Promise}
 */
export const msgNone = (title, duration = 1500) => {
  uni.showToast({
    title,
    icon: 'none',
    duration,
  })
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(true)
    }, duration)
  })
}

/**
 * @description 弹窗
 * @param {String} title 提示的文字
 * @param {String} content 提示的内容
 * @param {String} confirmText 确认按钮的文字
 * @param {String} cancelText 取消按钮的文字
 */
export const showModal = (option) => {
  return new Promise<void>((resolve, reject) => {
    uni.showModal({
      ...option,
      success(res) {
        if (res.confirm) {
          resolve(true)
        } else if (res.cancel) {
          reject(false)
        }
      },
      fail() {
        reject(false)
      },
    })
  })
}

/**
 * @description 预览图片
 * @param {Number} index 当前显示图片的索引值
 * @param {Array} list 需要预览的图片链接列表
 */
export function previewImage(index, list) {
  uni.previewImage({ current: index, urls: list })
}

/**
 * @description 获取导航栏配置
 */
export function useNavBarConfig() {
  let statusBarHeight = uni.getStorageSync('statusBarHeight')
  let titleBarHeight = uni.getStorageSync('titleBarHeight')
  let optAreaWidth = uni.getStorageSync('optAreaWidth') // 操作区域宽度

  // 避免每次都需要请求
  if (!statusBarHeight || !titleBarHeight || !optAreaWidth) {
    // 计算导航栏高度
    const systemInfo = uni.getSystemInfoSync()
    statusBarHeight = systemInfo.statusBarHeight
    titleBarHeight = 44 // 默认导航栏高度44px
    optAreaWidth = 100 // 默认操作区域宽度
    // #ifdef MP
    // 小程序中根据胶囊高度计算导航栏高度
    const menu = wx.getMenuButtonBoundingClientRect()
    titleBarHeight = Math.abs(menu.top - statusBarHeight) * 2 + menu.height
    // 计算操作区域宽度，如果是小程序，顶部气泡按钮一样宽
    optAreaWidth = (systemInfo.screenWidth - menu.right) * 2 + menu.width
    // #endif
    uni.setStorageSync('statusBarHeight', statusBarHeight)
    uni.setStorageSync('titleBarHeight', titleBarHeight)
  }

  return {
    statusBarHeight,
    titleBarHeight,
    navbarHeight: statusBarHeight + titleBarHeight,
    optAreaWidth,
  }
}

/**
 * 获取地理位置
 * @param showDialog 是否显示弹窗提示
 */
export function getLocation(showDialog = true) {
  const cLocation = uni.getStorageSync('cLocation')
  const time = 1 * 60 * 1000 // 超时时间
  return new Promise((resolve, reject) => {
    if (!cLocation.createTime || Date.now() > cLocation.createTime + time) {
      // #ifdef H5
      // 默认反回云南测试
      resolve({
        latitude: '25.60',
        longitude: '100.25',
      })
      // #endif
      // #ifdef MP-WEIXIN
      uni.getLocation({
        type: 'gcj02',
        // #ifdef MP-WEIXIN
        altitude: false,
        isHighAccuracy: false,
        // #endif
        success(res) {
          res.createTime = Date.now()
          uni.setStorageSync('cLocation', res)
          resolve(res)
        },
        fail: (err) => {
          if (showDialog && err.errCode == 2) {
            showModal({
              title: '请授权获取定位',
              content: '需要开启移动设备的位置/GPS',
            })
              .then(() => {})
              .catch(() => {})
          }
          reject(err)
        },
      })
      // #endif
    } else {
      resolve(cLocation)
    }
  })
}

// 距离换算
export function distance(num) {
  if (num >= 1000) {
    return (num / 1000).toFixed(2) + '公里'
  } else {
    return num + '米'
  }
}

// 打开地图
export function openLocation({ latitude, longitude, name, address }) {
  uni.openLocation({
    latitude,
    longitude,
    name,
    address,
    scale: 18,
  })
}

/**
 * 获取字典
 * @param code
 * @returns
 */
export function getDict(code) {
  return http.get('/blade-system/dict-biz/open/dictionary', {
    code,
  })
}

/**
 * 图片切割
 * @param imgs
 * @returns
 */
export function imgsSplit(imgs) {
  return imgs.split(',')
}

/**
 * 身份证脱敏
 * @param idCard
 * @returns
 */
export function desensitizeIDCard(idCard) {
  if (!idCard) return ''
  return idCard.replace(/(\d{6})\d{6}(\d{5})/, '$1******$2')
}

/**
 * 手机号脱敏
 * @param phoneNumber
 * @returns
 */
export function desensitizePhone(phoneNumber) {
  if (!phoneNumber) return ''
  return phoneNumber.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')
}

/**
 * 支付
 * @param params
 * @returns
 */
export function wxPay(params) {
  return new Promise((resolve, reject) => {
    uni.requestPayment({
      provider: 'wxpay',
      ...params,
      success: (res) => {
        resolve(res)
      },
      fail: (err) => {
        reject(err)
      },
    })
  })
}

// 酒店订单状态
export const orderStatus = [
  { label: '已取消', value: -1 },
  { label: '待支付', value: 0 },
  { label: '待入住', value: 1 },
  { label: '入住中', value: 2 },
  { label: '已退房', value: 3 },
]
